﻿using WH.Contracts.Systems.Organizations;
using WH.Model.Systems;
using WH.Repositories.IRepositories.ISystem;
using WH.Services.BaseService;
using WH.Services.IServices.ISystem;
using Rw.Core.Common.Paging;
using WH.Common.Paging;
using SqlSugar;

namespace WH.Services.Services.System
{
    public class OrganizationService : BaseService<OrganizationEntity>, IOrganizationService
    {
        private readonly IOrganizationRepository _organizationRepository;

        public OrganizationService(IOrganizationRepository organizationRepository) : base(organizationRepository)
        {
            _organizationRepository = organizationRepository;
        }

        public async Task<IPagedList<OrganizationEntity>> GetOrganizationsByPageAsync(PageParam pager, OrganizationFilter filter)
        {
            var query = Expressionable.Create<OrganizationEntity>(); ;//org => org.Layer == filter.Layer

            if (!string.IsNullOrWhiteSpace(filter.Keyword))
            {
                filter.Keyword = filter.Keyword.Trim();
                query.And(org => org.Code.Contains(filter.Keyword) || org.Name.Contains(filter.Keyword));
            }

            if (!string.IsNullOrWhiteSpace(filter.Name))
            {
                filter.Name = filter.Name.Trim();
                query.And(org => org.Name.Contains(filter.Name));
            }

            if (!string.IsNullOrWhiteSpace(filter.Code))
            {
                filter.Code = filter.Code.Trim();
                query.And(org => org.Code.Contains(filter.Keyword));
            }

            if (filter.IsEnable.HasValue)
            {
                query.And(org => org.IsEnable == filter.IsEnable.Value);
            }


            if (!string.IsNullOrWhiteSpace(filter.Id))
            {
                query.And(org => org.Id == filter.Id);
            }

            if (!string.IsNullOrWhiteSpace(filter.ParentId))
            {
                query.And(org => org.ParentId == filter.ParentId);
            }

            //query.And(org => org.Layer == SqlFunc.Subqueryable<OrganizationEntity>().Where(query.ToExpression()).Min(x => x.Layer));

            var paged = await _organizationRepository.PagedFindAllAsync(query.ToExpression(), pager);
            return paged;
        }

        public async Task<bool> SoftRemoveAsync(OrganizationEntity organization)
        {
            var org = await _organizationRepository.FindByIdAsync(organization.Id);

            org.IsDelete = true;

            return await UpdateAsync(org) > 0;
        }

        /// <summary>
        /// 根据机构id获取相应机构及所有下级机构id集合
        /// </summary>
        /// <param name="organizeId"></param>
        /// <returns></returns>
        public async Task<IList<OrganizationEntity>> GetOrganizeSelfAndSubsAsync(string organizeId)
        {
            if (string.IsNullOrWhiteSpace(organizeId))
            {
                return new List<OrganizationEntity>();
            }

            var list = await _organizationRepository.FindAllAsync(o => o.IsEnable, true);
            if (list == null || !list.Any())
            {
                return new List<OrganizationEntity>();
            }

            var org = list.FirstOrDefault(o => o.Id == organizeId);
            if (org == null)
            {
                return new List<OrganizationEntity>();
            }

            var result = new List<OrganizationEntity>();
            GetOrganizationIds(organizeId, list.ToList(), result);


            var ids = new List<OrganizationEntity> { org };
            ids.AddRange(result);

            return ids;
        }

        private void GetOrganizationIds(string parentId, List<OrganizationEntity> list, List<OrganizationEntity> result)
        {
            if (list == null)
            {
                return;
            }

            var ss = list.Where(l => l.ParentId == parentId).ToList();
            if (ss.Any())
            {
                result.AddRange(ss);
                foreach (var s in ss)
                {
                    GetOrganizationIds(s.Id, list, result);
                }
            }
        }


        /// <summary>
        /// 根据机构id获取相应机构及所有下级机构id集合
        /// </summary>
        /// <param name="organizeId"></param>
        /// <returns></returns>
        public async Task<IEnumerable<string>> GetOrganizeSelfAndSubIdsAsync(string organizeId)
        {
            if (string.IsNullOrWhiteSpace(organizeId))
            {
                return new List<string>();
            }

            var list = await _organizationRepository.FindAllAsync(x => x.IsEnable, true);
            if (list == null || !list.Any())
            {
                return new List<string>();
            }

            var result = new List<OrganizationEntity>();
            GetOrganizationIds(organizeId, list.ToList(), result);

            var ids = new List<string> { organizeId };
            ids.AddRange(result.Select(o => o.Id));

            return ids;
        }


        /// <summary>
        /// 根据机构id获取相应机构及所有上级级机构id集合
        /// </summary>
        /// <param name="organizeId"></param>
        /// <returns></returns>
        public async Task<IEnumerable<string>> GetOrganizeSelfAndParentIdsAsync(string organizeId)
        {
            if (string.IsNullOrWhiteSpace(organizeId))
            {
                return new List<string>();
            }

            var list = await _organizationRepository.FindAllAsync(null, true);
            if (list == null || !list.Any())
            {
                return new List<string>();
            }

            var result = new List<OrganizationEntity>();
            GetOrganizeParentIds(organizeId, list.ToList(), result);

            var ids = result.Select(o => o.Id);

            return ids;
        }


        private void GetOrganizeParentIds(string subId, List<OrganizationEntity> list, List<OrganizationEntity> result)
        {
            if (list == null)
            {
                return;
            }

            var ss = list.Where(l => l.Id == subId).ToList();
            if (ss.Any())
            {
                result.AddRange(ss);
                foreach (var s in ss)
                {
                    GetOrganizeParentIds(s.ParentId, list, result);
                }
            }
        }

        public async Task<string?> GetFullOrgName(string? orgId)
        {
            var orgs = await _organizationRepository.FindAllAsync(null, true);

            var org = orgs.FirstOrDefault(x => x.Id == orgId);

            if (org is null)
            {
                return default;
            }

            var idArr = org.Link?.Split('|');

            var fullnames = new List<string>();

            if (idArr is not null && idArr.Length > 0)
            {

                foreach (var id in idArr)
                {
                    var o = orgs.FirstOrDefault(x => x.Id == id);

                    if (o is not null)
                    {
                        fullnames.Add(o.Name);
                    }
                }
            }

            return string.Join(@"/", fullnames);
        }
    }
}
